//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "UI/Widgets/Label.h"

namespace Engine
{
namespace UI
{

	class Button;
	SHARED_POINTER( Button );



	//
	// Button
	//

	class Button : public Label
	{
		friend struct ::MetaData::ButtonCfg;

	// variables
	protected:
		UIAction			_onClick;
		bool				_checkedState;	// if true then check box style
		bool				_checked;		// if _checkedState == true


	// methods
	public:
		Button (EWidget::type wgtType, const EngineSubSystemsRef ess);
		~Button ();
		
		bool IsChecked () const			{ return _checkedState and _checked; }

		void SetChecked (bool checked);

		bool ProcessMessage (const WidgetMsg &msg) override;
		
		static ButtonPtr	New (const EngineSubSystemsRef ess);


	protected:
		bool _Update (const WidgetMsg &msg);
		bool _SetState (const WidgetMsg &msg);
	};


	
/*
=================================================
	constructor
=================================================
*/
	inline Button::Button (EWidget::type wgtType, const EngineSubSystemsRef ess) :
		Label(wgtType, ess), _checkedState(false), _checked(false)
	{}

/*
=================================================
	destructor
=================================================
*/
	inline Button::~Button ()
	{}
	
/*
=================================================
	ProcessMessage
=================================================
*/
	inline bool Button::ProcessMessage (const WidgetMsg &msg)
	{
		typedef WidgetMsg	WM;

		switch ( msg.GetType() )
		{
			case WM::UPDATE :		return _Update( msg );
			case WM::SET_STATE :	return _SetState( msg );
		}

		return Label::ProcessMessage( msg );
	}
		
/*
=================================================
	New
=================================================
*/
	inline ButtonPtr  Button::New (const EngineSubSystemsRef ess)
	{
		return BaseObject::_New( new Button( EWidget::BUTTON, ess ) );
	}

/*
=================================================
	_Update
=================================================
*/
	inline bool Button::_Update (const WidgetMsg &msg)
	{
		typedef WidgetMsg	WM;

		if ( not IsVisible() )
			return true;
		
		WM::Update const &		upd			= msg.To< WM::Update >();
		ColorStyle::EType const	prev_state	= _state;

		if ( _enabled )
		{
			const bool	is_inner = _region.IntersectRect( upd.data->TouchArea() );

			if ( is_inner and upd.data->IsPressed() )
			{
				upd.data->ResetTouch();
				_state = _checked ? ColorStyle::CHECKED_PRESSED : ColorStyle::IDLE_PRESSED;
			}
			else
			if ( is_inner and upd.data->IsClicked() )
			{
				upd.data->ResetTouch();

				if ( _checkedState )
				{
					_checked = not _checked;
					_state   = _checked ? ColorStyle::CHECKED : ColorStyle::IDLE;
				}

				_onClick.Call( this );
			}
			else
				_state = _checked ? ColorStyle::CHECKED : ColorStyle::IDLE;
		}
		else
			_state = ColorStyle::DISABLED;
					
		_stateChanged = (prev_state != _state);
		_CheckChangedOnUpdate( msg );

		_SendToAllAttached( msg );
		return true;
	}
	
/*
=================================================
	SetChecked
=================================================
*/
	inline void Button::SetChecked (bool state)
	{
		typedef WidgetMsg	WM;
		ProcessMessage( WM( WM::SET_STATE, WM::SetState( WM::SetState::CHECKED, state, false ) ) );
	}
	
/*
=================================================
	_SetState
=================================================
*/
	inline bool Button::_SetState (const WidgetMsg &msg)
	{
		typedef WidgetMsg	WM;

		WM::SetState const &	st = msg.To< WM::SetState >();

		switch ( st.state )
		{
			case WM::SetState::ENABLED :	_enabled = st.value;	break;
			case WM::SetState::VISIBLE :	_visible = st.value;	break;
			case WM::SetState::CHECKED :	_checked = st.value;	break;
		}

		if ( not _enabled )
			_state = ColorStyle::DISABLED;
		else
			_state = _checked ? ColorStyle::CHECKED : ColorStyle::IDLE;

		if ( st.recursive ) {
			_SendToAllAttached( msg );
		}

		_stateChanged = true;
		return true;
	}


}	// UI
}	// Engine